package org.kuan.lab.common.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;

import org.kuan.lab.base.util.AppAttributes;
import org.kuan.lab.common.entity.RoleResource;
import org.kuan.lab.common.entity.User;
import org.kuan.lab.common.entity.UserResource;
import org.kuan.lab.common.service.LoginService;
import org.kuan.lab.common.util.Permission;
import org.kuan.lab.common.vo.ResourceVO;
import org.primefaces.component.breadcrumb.BreadCrumb;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

/**
 * Project: erp<br>
 * Description: 登录Backing Bean，存取当前操作菜单，菜单树，登录人信息等……<br>
 * Copyright (c) 2012<br>
 * All Rights Reserved.<br>
 * @author <a href="mailto:gly420@163.com">GuanLuYong</a><br>
 */
@Controller @Scope("session")
public class LoginBean implements Serializable {
	private static final long serialVersionUID = 1L;
	private final Logger log = LoggerFactory.getLogger(getClass());
	
	@Resource
	private LoginService loginService;
	// 当前登陆用户
	private User user;
	
	// 资源列表
	private List<ResourceVO> resources;
	// 当前选中的资源
	private ResourceVO resvo;
	
	// 面包屑
	private BreadCrumb bread;
	
	public LoginBean() {}
	
	@PostConstruct public void initLoginBean() {
		user = new User();
		user.setAccount("root");
		user.setPassword("root");
		resources = new ArrayList<ResourceVO>();
	}
	
	/**
	 * 用户登入
	 * @return
	 */
	public String login() {
		User u = loginService.findUserByAccount(user.getAccount());
		FacesContext context = FacesContext.getCurrentInstance();
		if(u == null) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "登录错误：", "登录名不正确。"));
			return "LoginFailure";
		} else if(!u.getPassword().equals(user.getPassword())) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "登录错误：", "登录密码不正确。"));
			return "LoginFailure";
		}
		// success
		Map<String, Object> map = context.getExternalContext().getSessionMap();
		if(map.get("user") != null) {
			map.remove("user");
		}
		map.put("user", u);
		user = u;
		resources.clear();
		
		findResourcesByCurrentUser();
		return "LoginSuccess";
	}
	
	/**
	 * 用户登出
	 * @return
	 */
	public String logout() {
		Map<String, Object> map = 
				FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
		if(map.get("user") != null) {
			map.remove("user");
		}
		return "/login/login.xhtml";
	}
	
	/**
	 * 构建当前用户树
	 * @return
	 * @deprecated
	 */
	public void buildMenuTree(List<ResourceVO> reses, TreeNode node) {
		Long pid = null;
		if(node.getData() instanceof String) {	// first time, get first level resource
			pid = 0l;
		} else if(node.getData() instanceof ResourceVO) {
			pid = ((ResourceVO) node.getData()).getId();
		}
		if(pid == null) {
			log.error("no resource's parent id, please check it.");
			return;
		}
		for(ResourceVO rv : reses) {
			if(rv.getRes().getParentId().longValue() == pid.longValue()) {
				TreeNode n;
				if(rv.getRes().getUrl().equals("")) {
					n = new DefaultTreeNode(rv, node);
				} else {
					n = new DefaultTreeNode("document", rv, node);
				}
				buildMenuTree(reses, n);
			}
		}
	}
	/**
	 * 查找当前用户所有的资源，并排序
	 */
	public void findResourcesByCurrentUser() {
		List<ResourceVO> tmp = new ArrayList<ResourceVO>();
		List<UserResource> userResources = loginService.getUserResources(user.getId());
		for(UserResource ur : userResources) {
			if((ur.getStatus().longValue()&1) == 1 || (ur.getRes().getStatus().longValue()&1) == 1
					&& ur.getRes().getType().equals(AppAttributes.ERP_RESOURCE_TYPE_MENU)) {
				tmp.add(new ResourceVO(ur.getRes(), ur.getPermission()));
			}
		}
		
		List<ResourceVO> tmp1 = new ArrayList<ResourceVO>();
		List<RoleResource> roleResources = loginService.getRoleResources(user.getId());
		for (RoleResource rr : roleResources) {
			boolean flag = false;
			for (ResourceVO rv : tmp) {
				if (rr.getRes().getId().compareTo(rv.getId()) == 0
						&& rr.getRes().getType().equals(AppAttributes.ERP_RESOURCE_TYPE_MENU)) {
					rv.setPermission(rv.getPermission().longValue() | rr.getPermission().longValue());
					flag = true;
					break;
				}
			}
			if (!flag) {
				tmp1.add(new ResourceVO(rr.getRes(), rr.getPermission()));
			}
		}
		tmp.addAll(tmp1);
		tmp1 = null;
		// 一级菜单
		for(ResourceVO rvo : tmp) {
			if(rvo.getRes().getParentId().longValue() == 0) {
				resources.add(rvo);
			}
		}
		Collections.sort(resources, new ResComparator());
		tmp.removeAll(resources);
		// 二级菜单
		for(ResourceVO rvo : resources) {
			List<ResourceVO> sonsRes = new ArrayList<ResourceVO>();
			for(ResourceVO r : tmp) {
				if(r.getRes().getParentId().longValue() == rvo.getRes().getId().longValue()) {
					sonsRes.add(r);
				}
			}
			Collections.sort(sonsRes, new ResComparator());
			rvo.setSons(sonsRes);
			tmp.removeAll(sonsRes);
		}
		tmp = null;
	}
	
	private class ResComparator implements Comparator<ResourceVO> {
		@Override
		public int compare(ResourceVO o1, ResourceVO o2) {
			return o1.getRes().getCode().compareTo(o2.getRes().getCode());
		}
	}
	/**
	 * 构建面包屑结构
	 */
	public void ensureBreadCrumb() {}
	/**
	 * 返回当前菜单的权限值
	 * @return
	 */
	public Permission getPermission() {
		return new Permission(resvo.getPermission());
	}

	// Getter & Setter
	public LoginService getLoginService() {
		return loginService;
	}

	public void setLoginService(LoginService loginService) {
		this.loginService = loginService;
	}

	public User getUser() {
		return user;
	}

	public List<ResourceVO> getResources() {
		return resources;
	}
	
	public BreadCrumb getBread() {
		return bread;
	}

	public ResourceVO getResvo() {
		return resvo;
	}

	public void setResvo(ResourceVO resvo) {
		this.resvo = resvo;
	}
	
}
